package com.jrfid.smartcabinet.demo.ui.taking

import android.app.Application
import android.os.CountDownTimer
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.serialport.SerialPortFinder
import android.view.View
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.jrfid.devicemanager.library.CMDData
import com.jrfid.devicemanager.library.DeviceType
import com.jrfid.devicemanager.library.DevicesManager
import com.jrfid.devicemanager.library.packet.ICCardPacketData
import com.jrfid.devicemanager.library.packet.MainBoardPacketData
import com.jrfid.smartcabinet.demo.R
import com.jrfid.smartcabinet.demo.base.BaseViewModel
import com.jrfid.smartcabinet.demo.db.AppDatabase
import com.jrfid.smartcabinet.demo.model.CabinetConfigInfoModel
import com.jrfid.smartcabinet.demo.model.TagInfoModel
import com.jrfid.smartcabinet.demo.ui.take_result.TakeResultFragmentArgs
import com.xgzx.veinmanager.VeinApi
import kotlinx.coroutines.*
import java.io.File
import java.lang.Exception

class TakingViewModel(application: Application, navController: NavController) : BaseViewModel(application, navController) {

    private var isTake = false
    private var tagArray: Array<TagInfoModel> = arrayOf()
    private var cabinetArray: Array<CabinetConfigInfoModel> = arrayOf()
    var isTakeMode = ObservableBoolean(false)
    var cancelBtnEnable = ObservableBoolean(true)
    var nextBtnEnable = ObservableBoolean(false)
    var nextBtnText = ObservableField(getString(R.string.btn_next))
    var stateText = ObservableField(getString(R.string.text_waiting_pick_up))
//    private var countDownTimer = object : CountDownTimer(15000, 1000) {
//        override fun onTick(millisUntilFinished: Long) {
//            nextBtnText.set(getStringFormat(R.string.btn_next_format, (millisUntilFinished / 1000).toInt()))
//        }
//
//        override fun onFinish() {
//            next()
//        }
//    }

    //    private val socketListener = object : SocketActionAdapter() {
//        override fun onSocketConnectionSuccess(info: ConnectionInfo?, action: String?) {
//            super.onSocketConnectionSuccess(info, action)
//            LogUtils.dTag(TAG, "连接成功")
//        }
//
//        override fun onSocketConnectionFailed(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketConnectionFailed(info, action, e)
////            ToastUtils.showShort("连接失败")
//            LogUtils.dTag(TAG, "连接失败")
//        }
//
//        override fun onSocketDisconnection(info: ConnectionInfo, action: String?, e: Exception?) {
//            super.onSocketDisconnection(info, action, e)
////            ToastUtils.showShort("连接断开")
//            LogUtils.dTag(TAG, "连接断开")
//        }
//
//        override fun onSocketReadResponse(info: ConnectionInfo, action: String, data: OriginalData) {
//            super.onSocketReadResponse(info, action, data)
//            val body = data.bodyBytes
//            val header = data.headBytes
//            LogUtils.dTag(TAG, "${info.ip}收到数据：${KTDataUtils.byteArrayToHex(header)} ${KTDataUtils.byteArrayToHex(body)}")
//            LogUtils.dTag(TAG, "${info.ip}收到数据：${String(header)} ${String(body)}")
//            val no = "${String(header)}${String(body)}"
//            val entity = AppDatabase.instance.getNFCInfoDao().findByCardNo(no)
//            if (entity != null) {
//                //开门
//                openTheDoorByIC(info.ip)
//            }
//        }
//
//        override fun onSocketWriteResponse(info: ConnectionInfo, action: String?, data: ISendable) {
//            super.onSocketWriteResponse(info, action, data)
//            LogUtils.dTag(TAG, "${info.ip}发送数据：${KTDataUtils.byteArrayToHex(data.parse())}")
//        }
//    }
    private var isOpenTheDoor = false
    private var fingerVeinThreadList = arrayListOf<Thread>()
//    private var nfcManagerList = arrayListOf<IConnectionManager>()
//    private lateinit var listener: SerialPortManager.OnSerialPortDataListener

    init {
//        主柜打开电子锁
//        EF 04 01 05 01 FA
//        打开电子锁 副柜02
//        EF 04 02 05 01 FB
//        ttyXRUB0   115200

//        SerialPortFinder().allDevices.forEach {
//            LogUtils.dTag("111", it)
//        }
//        SerialPortFinder().allDevicesPath.forEach {
//            LogUtils.dTag("111", it)
//        }
//        listener = object : SerialPortManager.OnSerialPortDataListener {
//            override fun onDataReceived(text: String) {
//                val array = text.split(" ")
//                when (array[3]) {
//                    "05" -> {
//                        //电控锁
//                        when (array[4]) {
//                            "02" -> {
//                                //开锁反馈
//                                onOpenTheDoor()
//                            }
//                            "03" -> {
//                                //关锁反馈
//                                onCloseTheDoor()
//                            }
//                        }
//                    }
//                }
//            }
//        }
//        SerialPortManager.instance.addOnSerialPortDataListener(listener)
    }

//    private val onReceiveMainBoardDataListener = object : Manager.OnSerialPortDataListener {
//
//        override fun onDataReceived(byteArray: ByteArray) {
////            LogUtils.d("main recv: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//            val len = byteArray[1].toInt()
//            val dataLen = len - 3
//            val cmd = byteArray[3]
//            val address = byteArray[2]
//            when (cmd) {
//                CMDData.Cabinet.CMD_CABINET_DOOR_STATE -> {
//                    if (byteArray[4] == 0x02.toByte()) {
//                        //开门
//                        onOpenTheDoor()
//                    } else if (byteArray[4] == 0x03.toByte()) {
//                        //关门
//                        onCloseTheDoor()
//                    }
//                }
//                CMDData.Cabinet.CMD_IC_ID_CARD_DATA -> {
//                    val cardData = ByteArray(dataLen)
//                    System.arraycopy(byteArray, 4, cardData, 0, cardData.size)
//                    if (cardData[0] == 0x02.toByte() && cardData[cardData.size - 1] == 0x03.toByte()) {
//                        viewModelScope.launch {
//                            val cardNo = KTDataUtils.byteArrayToHexTrim(cardData)
//                            val entity = AppDatabase.instance.getNFCInfoDao().findByCardNo(cardNo)
//                            if (entity != null) {
//                                //开门
//                                openTheDoorByIC(address)
//                            }
//                        }
//                    }
//                }
//            }
//        }
//
//        override fun onDataSend(byteArray: ByteArray) {
//            LogUtils.d("main send: ${KTDataUtils.byteArrayToHexTrim(byteArray)}")
//        }
//
//    }

    private val listener = object : DevicesManager.OnDeviceDataCallback {
        override fun onDataReceived(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {
            when (deviceType) {
                DeviceType.MainBoard -> {
                    val model = MainBoardPacketData(byteArray)
                    when (model.cmd) {
                        CMDData.MainBoard.CMD_CABINET_DOOR_STATE -> {
                            if (model.data.size == 1) {
                                if (model.data[0] == 0x02.toByte()) {
                                    //开锁反馈
                                    onOpenTheDoor()
                                } else if (model.data[0] == 0x03.toByte()) {
                                    //关锁反馈
                                    onCloseTheDoor()
                                }
                            }
                        }
                    }
                }
                DeviceType.IDCard -> {
                    viewModelScope.launch {
                        val model = ICCardPacketData(byteArray)
                        val entity = AppDatabase.instance.getNFCInfoDao().findByCardNo(model.getICCardNo())
                        if (entity != null) {
                            //开门
                            openTheDoorByIC(address)
                        }
                    }
                }
            }
        }

        override fun onDataSend(deviceType: DeviceType, address: Byte, byteArray: ByteArray) {

        }

    }

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
        DevicesManager.instance.addOnDeviceDataListener(listener)
//        MainBoardManager.instance.addOnSerialPortDataListener(onReceiveMainBoardDataListener)
    }

    fun onClickBackBtn(view: View) {
        navController.navigateUp()
    }

    fun onClickNextBtn(view: View) {
//        countDownTimer.cancel()
        countDownJob?.cancel()
        viewModelScope.launch(Dispatchers.Main) {
            next()
        }
    }

    private fun next() {
        if (navController.currentDestination?.id == R.id.takingFragment) {
            navController.navigate(
                R.id.action_takingFragment_to_takeResultFragment,
                TakeResultFragmentArgs(isTake = isTake, tagInfoArray = tagArray, cabinetArray = cabinetArray).toBundle()
            )
        }
    }

    fun setData(isTake: Boolean, tagArray: Array<TagInfoModel>, cabinetArray: Array<CabinetConfigInfoModel>) {
        this.isTake = isTake
        this.tagArray = tagArray
        this.cabinetArray = cabinetArray
        isTakeMode.set(isTake)
        stateText.set(getString(if (isTake) R.string.text_waiting_pick_up else R.string.text_waiting_replenishment))
        //遍历柜子连接设备
//        for (cabinet in cabinetArray) {
//            val thread = FingerVeinThread(cabinet)
//            thread.start()
//            fingerVeinThreadList.add(thread)
//            val manager = TCPConnectUtils.connectNFCDevice(cabinet.icIP.get(), cabinet.icPort.get()?.toIntOrNull(), socketListener)
//            nfcManagerList.add(manager)
//        }
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        DevicesManager.instance.removeOnDeviceDataListener(listener)
//        MainBoardManager.instance.removeOnSerialPortDataListener(onReceiveMainBoardDataListener)
//        SerialPortManager.instance.removeOnSerialPortDataListener(listener)
//        fingerVeinThreadList.forEach {
//            it.interrupt()
//        }
//        nfcManagerList.forEach {
//            it.unRegisterReceiver(socketListener)
//            it.disconnect()
//        }
    }

    fun onClickBtnTest1(view: View) {
        //模拟开门信号
        onOpenTheDoor()
    }

    fun onClickBtnTest2(view: View) {
        //模拟关门信号
        onCloseTheDoor()
    }

    private fun onOpenTheDoor() {
        //开门
        isOpenTheDoor = true
        stateText.set(getString(if (isTake) R.string.text_pick_up else R.string.text_replenishment))
        nextBtnText.set(getString(R.string.btn_next))
        //开门后，不能返回，不能下一步
        cancelBtnEnable.set(false)
        nextBtnEnable.set(false)
        //取消倒计时
//        countDownTimer.cancel()
        countDownJob?.cancel()
    }

    private fun onCloseTheDoor() {
        //关门
        isOpenTheDoor = false
        stateText.set(getString(if (isTake) R.string.text_pick_up_finish else R.string.text_replenishment_finish))
        //开门后，不能返回，能点击下一步
        cancelBtnEnable.set(false)
        nextBtnEnable.set(true)
        //开始倒计时5s，自动进入下一步
//        countDownTimer.start()
        countDownJob?.cancel()
        countDownJob = viewModelScope.launch {
            for (i in 15 downTo 0) {
                withContext(Dispatchers.Main) {
                    nextBtnText.set(getStringFormat(R.string.btn_next_format, i))
                }
                delay(1000)
            }
            withContext(Dispatchers.Main) {
                next()
            }
        }
    }

    private var countDownJob: Job? = null

    private fun openTheDoorByFinger(fingerIP: String) {
//        //门已开，不需要再次开门
//        if (isOpenTheDoor) {
//            return
//        }
//        //判断属于哪个柜子
//        val cabinet = cabinetArray.find { it.fingerIP.get() == fingerIP }
//        if (cabinet != null) {
//            SerialPortManager.instance.sendStringData(CMDData.Cabinet.openDoor(cabinet.address.get() ?: "01"))
//            //正式环境时屏蔽该行代码
////            onOpenTheDoor()
//        }
    }

    private fun openTheDoorByIC(icIP: String) {
        //门已开，不需要再次开门
//        if (isOpenTheDoor) {
//            return
//        }
//        //判断属于哪个柜子
//        val cabinet = cabinetArray.find { it.icIP.get() == icIP }
//        if (cabinet != null) {
//            SerialPortManager.instance.sendStringData(CMDData.Cabinet.openDoor(cabinet.address.get() ?: "01"))
//            //正式环境时屏蔽该行代码
////            onOpenTheDoor()
//        }
    }

    private fun openTheDoorByIC(address: Byte) {
        //门已开，不需要再次开门
        if (isOpenTheDoor) {
            return
        }
        DevicesManager.instance.sendData(deviceType = DeviceType.MainBoard, address = address, byteArray = CMDData.MainBoard.openCabinetDoor(address))
//        MainBoardManager.instance.sendByteData(CMDData.Cabinet.openCabinetDoor(address))
    }

    private inner class FingerVeinThread(private var info: CabinetConfigInfoModel) : Thread() {
        override fun run() {
            super.run()
            var searchHandle: Long? = null
            var devHandle: Long? = null
            try {
                devHandle = VeinApi.FVConnectDev("IP:${info.fingerIP.get()},PORT:${info.fingerPort.get()}", "00000000")
                if (devHandle > 0) {
                    LogUtils.dTag(TAG, "${info.name}指静脉设备连接成功")
                    while (true) {
                        if (!isInterrupted) {
                            if (searchHandle == null) {
                                val fingerCharaList = AppDatabase.instance.getFingerInfoDao().queryAll()
                                searchHandle = VeinApi.FVCreateVeinLib(fingerCharaList.size.toLong())
                                if (searchHandle <= 0) {
                                    LogUtils.dTag(TAG, "算法库创建失败：${searchHandle}")
                                    searchHandle = null
                                    sleep(1000)
                                    continue
                                } else {
                                    LogUtils.dTag(TAG, "算法库创建成功")
                                    fingerCharaList.forEach {
                                        val userId = VeinApi.FVGetNullID(searchHandle)
                                        val code = VeinApi.FVImportVeinTemp(searchHandle, userId, it.finger)
                                        if (code == 0L) {
                                            LogUtils.dTag(TAG, "用户${userId}模板导入算法库成功")
                                        } else {
                                            LogUtils.dTag(TAG, "用户${userId}模板导入算法库失败${code}")
                                        }
                                    }
                                }
                            }
                            val sChara = VeinApi.FVGetVeinChara(devHandle, 6000) //通过指静脉设备采集特征，等待手指放入超时为6秒
                            if (sChara.length < 10) {
                                //获取失败
                                val error = sChara.toIntOrNull()
                                val text = if (error == -16) {
                                    getString(R.string.text_finger_vein_not_support)
                                } else if (error == -11) {
                                    getString(R.string.text_finger_vein_no_fingers)
                                } else if (error == -17) {
                                    getString(R.string.text_finger_vein_incorrect)
                                } else {
                                    getStringFormat(R.string.text_finger_vien_error, sChara)
                                }
                                LogUtils.dTag(TAG, text)
                                sleep(1000)
                                continue
                            } else {
                                //获取成功
                                LogUtils.dTag(TAG, "特征值获取成功：${sChara}")
                                val userId = VeinApi.FVSearchUser(searchHandle, sChara, 2)
                                if (userId > 0) {
                                    //识别成功，开门
                                    openTheDoorByFinger(info.fingerIP.get()!!)
                                } else {
                                    //未注册
                                    LogUtils.dTag(TAG, "该手指未注册")
                                }
                            }
                        }
                    }
                } else {
                    LogUtils.dTag(TAG, "连接失败")
                }
            } catch (e: Exception) {
                e.printStackTrace()
            } finally {
                devHandle?.let {
                    VeinApi.FVCloseDev(devHandle)
                }
                searchHandle?.let {
                    VeinApi.FVDestroyVeinLib(searchHandle)
                }
            }
        }
    }
}